#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <omp.h>
#include "aes.h"

int main(int argc, char* argv[])
{
	FILE *keyfile, *infile, *outfile;
	uint8_t *key_val;
	uint8_t *file_chunks;
	struct stat buf;
	int i;
	int file_size, key_size, blocks;
	char* key_str,*outfile_name;
	char rem_bytes;
	Key *key;
	KEY_TYPE key_type;
	int samples;
	double start_time, total_time = 0;
	
	if(argc != 3)
	{
		printf("Usage: ./aesencrypt <filename> <keyfile>\n");
		exit(1);
	}
	
	infile = fopen(argv[1], "rb");
	
	if(infile == NULL)
	{
		printf("Could not open input file %s.\n",argv[1]);
		exit(1);
	}
	
	keyfile = fopen(argv[2], "r");
	
	if(keyfile == NULL)
	{
		printf("Could not open keyfile.\n");
		exit(1);
	}
	
	outfile_name = (char*)malloc(strlen(argv[1])+5);
	strcpy(outfile_name,argv[1]);
	strcat(outfile_name,".dec");
	
	outfile = fopen(outfile_name,"wb");
	free(outfile_name);
	
	if(outfile == NULL)
	{
		printf("Could not open output file %s.\n",outfile_name);
		exit(1);
	}
	
	fstat(fileno(keyfile), &buf);
	
	file_size = buf.st_size;
	
	blocks = file_size/2;
	
	key_size = blocks*8;
	
	key_str = (char*)calloc(3,sizeof(char));
	
	key_val = (uint8_t*)malloc(blocks*sizeof(uint8_t));
	
	for(i = 0; i < 2*blocks; i+=2)
	{
		fread((void*)(key_str),1,2,keyfile);
		//printf("%d: %s\n",i/8,key_str);
		key_val[i/2] = (uint8_t)strtoul(key_str,NULL,16);
	}
	
	free(key_str);
	
	switch(key_size)
	{
		case 128:
		key_type = KEY_128;
		break;
		
		case 192:
		key_type = KEY_192;
		break;
		
		case 256:
		key_type = KEY_256;
		break;
		
		default:
		printf("Invalid key length (%d bits). Must be 128, 192, or 256 bits.\n",key_size);
		free(key_val);
		exit(1);
		break;
	};
	/*for(i = 0; i < blocks; i++)
	{
		printf("%#lx\n",key[i]);
	}*/
	
	//gen_subkeys(key,key_size);
	key = new_key_dec(key_type,key_val);
	
	fstat(fileno(infile), &buf);
	
	file_size = buf.st_size;
	
	//Get number of padding bytes
	fseek(infile,-1,SEEK_END);
	fread((void*)(&rem_bytes),1,1,infile);
	rewind(infile);
	
	file_chunks = (uint8_t*)calloc(file_size+rem_bytes,sizeof(uint8_t));
	fread((void*)(file_chunks),1,file_size,infile);
	for(samples = 0; samples < NUM_SAMPLES; samples++)
	{
		start_time = omp_get_wtime();
		key = new_key(key_type,key_val);
		
		for(i = 0; i < file_size-1; i+=16)
		{
			aes_decrypt(file_chunks+i,key);
		}
		total_time += omp_get_wtime() - start_time;
		free(key);
	}
	//fwrite((void*)(&rem_bytes),1,1,outfile);
	fwrite((void*)file_chunks,1,file_size-rem_bytes-1,outfile);
	printf("1,%.9f\n",total_time/(double)(NUM_SAMPLES));
	
	fclose(keyfile);
	fclose(infile);
	fclose(outfile);
	free(key_val);
	return 0;
}
